package com.chuiyuan.utils;

import java.util.LinkedList;

/**
 * Created by chuiyuan on 2/21/16.
 * start:
 * create a new thread and run the job in run()
 * run:
 * not create any new thread, just run job in current thread
 *
 * TO DO:
 * (1)how to stop the thread ?
 */
public class MyWorkQueue {
    //Executors
    /**
     * thread pool size
     */
    private final int n ;
    /**
     * Runnable job queue,LinkedList
     */
    private final LinkedList queue ;
    /**
     *
     */
    private final PoolWorker [] threads ;
    /**
     * init n threads for workers,
     * start all work threads
     * @param n  thread pool size
     */
    public MyWorkQueue(int n){
        this.n = n;
        queue = new LinkedList();
        threads = new PoolWorker[n];

        for (int i=0;i<n ;i++){
            threads[i] = new PoolWorker();//if no,NullPointerException
            threads[i].start();//start all work threads
        }
    }

    /**
     * work thread
     */
    private class PoolWorker extends Thread{
        public void run(){
            Runnable r =null;
            while(true){
                synchronized (queue){
                    //if queue is empty, wait
                    while (queue.isEmpty()){
                        try {
                            queue.wait(10);
                        }catch (InterruptedException e){

                        }
                    }
                    //if queue not empty,get job from queue and do it
                    //if change LinkedList to blocking queue?
                    //this must in synchronized
                    if (!queue.isEmpty()) {
                        r = (Runnable) queue.removeFirst();
                    }
                }
                //out of synchronized
                try {
                    if (r!= null) r.run();
                }catch (RuntimeException e){}

            }
        }
    }

    /**
     * add and execute Runnable job
     * @param r
     */
    public void execute(Runnable r ){
        synchronized (queue){
            queue.addLast(r);
            queue.notify();
        }
    }

}
